/************************************************************************
	DBZ Server Query Sample by Samson Chen, May 8, 1995
	Code modified from INNBBSD-0.40 by Shih-Kun Huang
 ------------------------------------------------------------------------

	SYNOPSIS
	  init_dbz_channel()

	  close_dbz_channel()

	  add_mid(mid, path)
		char *mid;
		char *path;

	  query_mid(mid, path)
		char *mid;
		char *path;

	DESCRIPTION
	  make sure that #define DBZ_CHANNEL is the correct UNIX domain
	  socket path.

	  call init_dbz_channel() before using add_mid() and query_mid(),
	  return TRUE(-1) if successful, FALSE(0) if failed.
	  call close_dbz_channel() when program exit.

	  add_mid() put *mid and *path to dbz server. Return TRUE if
	  successful, FALSE if failed(maybe duplicate).

	  query_mid() search *mid from dbz server, if found, path will be
	  put to *path. If you call query_mid(*mid, NULL) then the function
	  just do searching. Return TRUE if found, FALSE if not found.

	  Comment the definition DBZ_CHANNEL (do not declare it) will stop
	  the dbz function automatically.

	  There is a sample main() on the bottom of this prgram, replace
	  it with your own.
 ************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define	DBZ_CHANNEL	"innd/.innbbsd"

#define TRUE	-1
#define	FALSE	0

char INNBBSbuffer[4096];

static FILE *innbbsin, *innbbsout;
static int innbbsfd;
static char dbz_connect = FALSE;

#ifdef SOLARIS
#ifndef bzero
#define bzero(mem, size) memset(mem,'\0',size)
#endif
#endif

int close_dbz_channel(void);

/*
	add Message-ID to DBZ server
*/
int add_mid(const char *mid,const char *path){
    if (dbz_connect) {
        fprintf(innbbsout, "ADDHIST %s %s\r\n", mid, path);
        fflush(innbbsout);
        fgets(INNBBSbuffer, sizeof INNBBSbuffer, innbbsin);

        if (INNBBSbuffer[0] == '2')
            return (TRUE);
        else
            return (FALSE);
    } else
        return (FALSE);
}

/*end of add_mid*/

/*
	query Message-ID from DBZ server
*/
int query_mid(const char *mid,char *path){
    char line[4096];
    char *l;
    int c;

    if (dbz_connect) {
        sprintf(line, "GREPHIST %s\r\n", mid);
        fprintf(innbbsout, "%s", line);
        fflush(innbbsout);
        fgets(INNBBSbuffer, sizeof INNBBSbuffer, innbbsin);

        if (INNBBSbuffer[0] == '2') {
            if (path == (char *) NULL)
                return (TRUE);

            sprintf(line, "%s            ", INNBBSbuffer);
            l = line;

            /*
             * find path 
             */
            c = 0;
            while (l[c] != 0 && l[c] != 0x9 && l[c] != 0x20)
                c++;
            l += c + 1;

            c = 0;
            while (l[c] != 0 && l[c] != 0x9 && l[c] != 0x20)
                c++;
            l += c + 1;

            c = 0;
            while (l[c] != 0 && l[c] != 0x9 && l[c] != 0x20)
                c++;
            l[c] = 0;

            strcpy(path, l);

            return (TRUE);

        } else
            return (FALSE);
    } else
        return (FALSE);

}

/*end of query_mid*/

/*
	open UNIX DOMAIN socket
*/
int dbzunixclient(const char *path){
    struct sockaddr_un s_un;    /* unix endpoint address */
    int s;

    bzero((char *) &s_un, sizeof(s_un));
    s_un.sun_family = AF_UNIX;

    if (path == NULL)
        return (-1);

    strcpy(s_un.sun_path, path);

    /*
     * Allocate a socket 
     */
    s = socket(PF_UNIX, SOCK_STREAM, 0);
    if (s < 0)
        return -1;

    /*
     * Connect the socket to the server 
     */
    if (connect(s, (struct sockaddr *) &s_un, sizeof(s_un)) < 0)
        return -1;

    return s;
}

/*end of unixclient*/

/*
	init dbz unix domain socket
*/
int init_dbz_channel(void){
    dbz_connect = FALSE;
#ifdef DBZ_CHANNEL
    innbbsfd = dbzunixclient(DBZ_CHANNEL);

    if (innbbsfd < 0)
        return (FALSE);

    if ((innbbsin = fdopen(innbbsfd, "r")) == NULL || (innbbsout = fdopen(innbbsfd, "w")) == NULL)
        return (FALSE);

    dbz_connect = TRUE;

    /*
     * dbz server responsed initial status 
     */
    fgets(INNBBSbuffer, sizeof(INNBBSbuffer), innbbsin);
    if (strncmp(INNBBSbuffer, "200", 3)) {
        dbz_connect = FALSE;
        close_dbz_channel();
    }
#endif
    return (dbz_connect);
}

/*end of initsocket*/

/*
	close dbz channel
*/
int close_dbz_channel(void){
    if (dbz_connect) {
        if (innbbsin != NULL)
            fclose(innbbsin);
        if (innbbsout != NULL)
            fclose(innbbsout);
        if (innbbsfd >= 0)
            close(innbbsfd);
    }
    return 0;
}

/*end of closesocket*/

/***********************************************************************
		Just a SAMPLE, replace main() with your own
 ***********************************************************************/
int main(int argc,char **argv){
    char test[4096];
    int ret;

    init_dbz_channel();

    ret = add_mid("<tttt.eeee.ssss.tttt>", "THIS_IS_1ST_PATH");
    if (ret)
        printf("add 1st mid OK\n");
    else
        printf("add 1st mid failed\n");

    ret = add_mid("<bbbb.cccc.dddd.eeee>", "THIS_IS_2ND_PATH");
    if (ret)
        printf("add 2st mid OK\n");
    else
        printf("add 2st mid failed\n");

    ret = query_mid("<tttt.eeee.ssss.tttt>", test);
    if (ret)
        printf("query 1st ok : '%s'\n", test);
    else
        printf("query 1st failed\n");

    ret = query_mid("<bbbb.cccc.dddd.eeee>", test);
    if (ret)
        printf("query 2nd ok : '%s'\n", test);
    else
        printf("query 2nd failed\n");

    ret = query_mid("<no.such.item>", test);
    if (ret)
        printf("query no_such_item found ??? : '%s'\n", test);
    else
        printf("query no_such_item not found\n");

    close_dbz_channel();
    return 0;
}

